package edu.byu.intex2.data.bo;

import edu.byu.intex2.data.DataException;
import edu.byu.intex2.data.dao.SaleDAO;
import edu.byu.intex2.data.dao.SalespersonDAO;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import magis.SaleItem;

/**
 * Sale keeps track of a logical sale made by a salesperson.
 * @author Brady
 */
public class Sale extends BusinessObject {

    private double totalPrice;
    private double tax;
    private String financed;
    private double downPayment;
    private String paymentPlan;
    private double discount;
    private Date date;
    /** Salesperson */
    private String salespersonId;
    private Salesperson salesperson;
    private double salespersonBonus;
    /** Lines */
    private List<SaleLine> salesLines;
    private List<TradeInLine> tradeInLines;
    /** Customer */
    private String customerId;
    private Customer customer;
    /** Dealership */
    private Dealership dealership;
    private String dealershipId;

    // Sale Items -- used to compute the total
    private List<SaleItem> saleItems = new ArrayList<SaleItem>();

    /** Creates a new instance of BusinessObject */
    public Sale(String id) {
        super(id);
    }//constructor

    /** Convenience method to call the correct DAO to save this business object */
    public void save() throws DataException {
        try {
            SaleDAO.getInstance().save(this);
        } catch (DataException e) {
            e.printStackTrace();
        }
    }

    /**
     * @return the dealership
     */
    public Dealership getDealership() {
        return dealership;
    }

    /**
     * @param dealership the dealership to set
     */
    public void setDealership(Dealership dealership) {
        this.dealership = dealership;
        setDirty(true);
    }

    /**
     * @return the salesLines
     */
    public List<SaleLine> getSalesLines() {
        if (salesLines == null) {
            salesLines = new ArrayList<SaleLine>();
        }
        return salesLines;
    }

    /**
     * @return the tradeInLines
     */
    public List<TradeInLine> getTradeInLines() {
        if (tradeInLines == null) {
            tradeInLines = new ArrayList<TradeInLine>();
        }
        return tradeInLines;
    }

    /**
     * @return the totalPrice
     */
    public double getTotalPrice() {
        return totalPrice;
    }

    /**
     * @param totalPrice the totalPrice to set
     */
    public void setTotalPrice(double totalPrice) {
        this.totalPrice = totalPrice;
        setDirty(true);
    }

    /**
     * @return the tax
     */
    public double getTax() {
        return tax;
    }

    /**
     * @param tax the tax to set
     */
    public void setTax(double tax) {
        this.tax = tax;
        setDirty(true);
    }

    /**
     * @return the financed
     */
    public String getFinanced() {
        return financed;
    }

    /**
     * @param financed the financed to set
     */
    public void setFinanced(String financed) {
        this.financed = financed;
        setDirty(true);
    }

    /**
     * @return the downPayment
     */
    public double getDownPayment() {
        return downPayment;
    }

    /**
     * @param downPayment the downPayment to set
     */
    public void setDownPayment(double downPayment) {
        this.downPayment = downPayment;
        setDirty(true);
    }

    /**
     * @return the paymentPlan
     */
    public String getPaymentPlan() {
        return paymentPlan;
    }

    /**
     * @param paymentPlan the paymentPlan to set
     */
    public void setPaymentPlan(String paymentPlan) {
        this.paymentPlan = paymentPlan;
        setDirty(true);
    }

    /**
     * @return the discount
     */
    public double getDiscount() {
        return discount;
    }

    /**
     * @param discount the discount to set
     */
    public void setDiscount(double discount) {
        this.discount = discount;
        setDirty(true);
    }

    /**
     * @return the date
     */
    public Date getDate() {
        return date;
    }

    /**
     * @param date the date to set
     */
    public void setDate(Date date) {
        this.date = date;
        setDirty(true);
    }

    /**
     * @return the salespersonBonus
     */
    public double getSalespersonBonus() {
        return salespersonBonus;
    }

    /**
     * @param salespersonBonus the salespersonBonus to set
     */
    public void setSalespersonBonus(double salespersonBonus) {
        this.salespersonBonus = salespersonBonus;
        setDirty(true);
    }

    /**
     * @param salesLines the salesLines to set
     */
    public void setSalesLines(List<SaleLine> salesLines) {
        this.salesLines = salesLines;
        setDirty(true);
    }

    /**
     * Add a saleLine
     * @param saleLine to add
     */
    public void addSaleLine(SaleLine saleLine) {
        getSalesLines().add(saleLine);

        // Add the relating sale Item
        SaleItem si = new SaleItem();
        try {
            si.setDescription(saleLine.getPhysicalCar().getVin());
        } catch (Exception e) {
            e.printStackTrace();
        }
        si.setPrice(saleLine.getActualPrice());
        si.setReferenceId(getId());

        // Add Sale Item
        getSaleItems().add(si);

        // Set Dirty
        setDirty(true);
    }

    /** Remove a sale line 
     * @param saleLine  to remove
     */
    public void removeSaleLine(SaleLine saleLine) {
        getSalesLines().remove(saleLine);

        // Remove relating saleItem
        for (SaleItem si : getSaleItems()) {
            if (si.getReferenceId().equals(id)) {
                getSaleItems().remove(si);
                break;
            }
        }

        setDirty(true);
    }

    /**
     * @param tradeInLines the tradeInLines to set
     */
    public void setTradeInLines(List<TradeInLine> tradeInLines) {
        this.tradeInLines = tradeInLines;
        setDirty(true);
    }

    /**
     * Add a tradeInLine
     * @param tradeInLine to add
     */
    public void addTradeInLine(TradeInLine tradeInLine) {
        getTradeInLines().add(tradeInLine);

        // Add the relating sale Item
        SaleItem si = new SaleItem();
        try {
            si.setDescription(tradeInLine.getUsedCar().getVin());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Price is negative in a tradeInLine
        si.setPrice((0 - tradeInLine.getTradeInValue()));
        si.setReferenceId(getId());

        // Add Sale Item
        getSaleItems().add(si);
    }

    /** Remove a trade in  line
     * @param tradeinline  to remove
     */
    public void removeTradeInLine(TradeInLine tradeInLine) {
        getTradeInLines().remove(tradeInLine);

        // Remove relating saleItem
        for (SaleItem si : getSaleItems()) {
            if (si.getReferenceId().equals(id)) {
                getSaleItems().remove(si);
                break;
            }
        }

        setDirty(true);
    }

    /**
     * @return the salespersonId
     */
    public String getSalespersonId() {
        return salespersonId;
    }

    /**
     * @param salespersonId the salespersonId to set
     */
    public void setSalespersonId(String salespersonId) {
        this.salespersonId = salespersonId;
        setDirty(true);
    }

    /**
     * @return the salesperson from the DAO
     */
    public Salesperson getSalesperson() {
        if (salesperson == null) {
            try {
                salesperson = SalespersonDAO.getInstance().read(salespersonId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return salesperson;
    }

    /**
     * @param salesperson the salesperson to set
     */
    public void setSalesperson(Salesperson salesperson) {
        this.salesperson = salesperson;
    }

    /**
     * @return the saleItems
     *    Sale Items -- used to compute the total
     */
    public List<SaleItem> getSaleItems() {
        return saleItems;
    }

    /**
     * @param saleItems the saleItems to set
     */
    public void setSaleItems(List<SaleItem> saleItems) {
        this.saleItems = saleItems;
    }
}
